package multi_thread.master.tools;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAdder;

/**
 * @author Cheng Jun
 * Description: AtomicLong 在高并发的情况下，会有大量的自旋操作，消耗CPU。
 * 使用 LongAdder 可以更好地应对 高并发情况，发挥 CPU的极致性能。原理是 生成 Cell[]，AtomicLong是对一个数字进行CAS操作，
 * 而 LongAdder是对 数组的 数字进行CAS操作，然后数组的数字都累加起来。
 * 利用了空间换时间的思想
 * @version 1.0
 * @date 2022/5/20 16:49
 * @see LongAdder
 * @see ThreadLocalRandomExample
 */
public class LongAdderExample {

    public static void main(String[] args) {
        // 千万并发的情况下 会有 十几倍的性能差异
        LongAdder atomicNum = new LongAdder();
        AtomicLong atomicLong = new AtomicLong(0L);
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(10);
        long startMilli = System.currentTimeMillis();
        for (int i = 0; i < 100; i++) {
            Runnable task = () -> {
                for (int j = 0; j < 1_000_000; j++) {
                    atomicNum.add(1);
                    // atomicLong.addAndGet(1);
                }
            };
            fixedThreadPool.execute(task);
        }
        fixedThreadPool.shutdown();

        // while (!fixedThreadPool.isTerminated()){
        //     // 只要有任务没结束就死循环
        // }

        try {
            while (!fixedThreadPool.awaitTermination(100, TimeUnit.MILLISECONDS)){
                System.out.println("只要有任务没结束就死循环！");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        long endMilli = System.currentTimeMillis();
        System.out.println("endMilli - startMilli = " + (endMilli - startMilli));
    }
}
